package com.nuanshui.heatedloan.credit.pay;

import com.aipg.common.AipgReq;
import com.alibaba.dubbo.config.annotation.Reference;
import com.nuanshui.framework.utils.LogUtil;
import com.nuanshui.framework.utils.model.Pair;
import com.nuanshui.heatedloan.constant.GlobalParam;
import com.nuanshui.heatedloan.constant.RabbitMqQueue;
import com.nuanshui.heatedloan.credit.constant.BorrowType;
import com.nuanshui.heatedloan.credit.pay.constant.OrderPayState;
import com.nuanshui.heatedloan.credit.pay.utils.AllinPayUtil;
import com.nuanshui.heatedloan.credit.pay.validation.ValidationResult;
import com.nuanshui.heatedloan.credit.pay.validation.ValidationResultCode;
import com.nuanshui.heatedloan.fund.constant.AccountBillStatus;
import com.nuanshui.heatedloan.fund.constant.AccountBillSubType;
import com.nuanshui.heatedloan.fund.constant.AccountBillType;
import com.nuanshui.heatedloan.fund.enums.PlatformEnum;
import com.nuanshui.heatedloan.fund.facade.OrderNumWithPayNumService;
import com.nuanshui.heatedloan.fund.facade.UserAccountBillService;
import com.nuanshui.heatedloan.fund.model.OrderNumWithPayNum;
import com.nuanshui.heatedloan.fund.model.UserAccountBill;
import com.nuanshui.heatedloan.middleware.rabbitmq.RabbitmqMessageSender;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import static com.nuanshui.heatedloan.constant.RabbitMqQueue.RABBIT_MQ_PAY_STATUS;

/**
 * 订单支付状态
 */
@Service
public class OrderPayStateService implements InitializingBean {

    private Logger logger = LoggerFactory.getLogger(OrderPayStateService.class);

    @Reference(url= GlobalParam.FUND_DUBBO_SERVER,timeout=GlobalParam.DUBBO_SERVER_TIME_OUT,version=GlobalParam.FUND_DUBBO_SERVER_VERSION)
    private OrderNumWithPayNumService orderNumWithPayNumService;

    @Reference(url= GlobalParam.FUND_DUBBO_SERVER,timeout=GlobalParam.DUBBO_SERVER_TIME_OUT,version=GlobalParam.FUND_DUBBO_SERVER_VERSION)
    private UserAccountBillService userAccountBillService;

    @Autowired
    private RabbitmqMessageSender rabbitmqMessageSender;

    private UserAccountBill generateAccountBill(PayRequest request,Integer state) {
        UserAccountBill uab = new UserAccountBill();
        uab.setUserId(request.getOrder().getUserId());

        Pair<Integer,Integer> status=getBillStatus(state);

        uab.setStatus(status.getKey());
        uab.setSubStatus(status.getValue());

        uab.setPlatform(PlatformEnum.PLATFORM_ALLIN.getName());
        uab.setOrderNumber(request.getOrderNo());
        String dealNum = PayContext.getContext().getPayNum();
        uab.setDealNum(dealNum);
        if (request.getBizType().equals(String.valueOf(BorrowType.SINGLELOAN))) {
            uab.setType(AccountBillType.TYPE_LOAN_SINGLE);
        } else if (request.getBizType().equals(String.valueOf(BorrowType.LIGHTLOAN))) {
            uab.setType(AccountBillType.TYPE_LOAN_LIGHT);
        }
        if (request.getTransRequestCode().equals(TransRequestCode.TRX_CODE_SINGLE_PAY)) {
            if (uab.getType().equals(AccountBillType.TYPE_LOAN_SINGLE)) {
                uab.setName(BorrowType.SINGLELOAN_NAME + "--借款");
            } else if (uab.getType().equals(AccountBillType.TYPE_LOAN_LIGHT)) {
                uab.setName(BorrowType.LIGHTLOAN_NAME + "--借款");
            }
            uab.setMoney((long) request.getMoney());
            uab.setSubType(AccountBillSubType.TYPE_PAY);
        } else if (request.getTransRequestCode().equals(TransRequestCode.TRX_CODE_REPAY)) {
            if (uab.getType().equals(AccountBillType.TYPE_LOAN_SINGLE)) {
                uab.setName(BorrowType.SINGLELOAN_NAME + "--还款");
            } else if (uab.getType().equals(AccountBillType.TYPE_LOAN_LIGHT)) {
                uab.setName(BorrowType.LIGHTLOAN_NAME + "--还款");
            }
            uab.setMoney((long) request.getMoney() * -1);
            uab.setSubType(AccountBillSubType.TYPE_REPAY);
        }


        userAccountBillService.insertBillRecord(uab);


        return uab;
    }

    private void generatePayNum(PayRequest request,Integer state)
    {

        String payNum=PayContext.getContext().getPayNum();

        OrderNumWithPayNum orderNumWithPayNum=new OrderNumWithPayNum();
        orderNumWithPayNum.setOrderNum(request.getOrderNo());
        orderNumWithPayNum.setMoney(request.getMoney());
        orderNumWithPayNum.setPayNum(payNum);

        orderNumWithPayNumService.save(orderNumWithPayNum);

        generateAccountBill(request,state);
    }

    private Pair<Integer,Integer> getBillStatus(Integer state)
    {
        Integer subStatus = state;
        Integer status = AccountBillStatus.CREATE;
        if (state == OrderPayState.STATE_BEGIN) {
            status = AccountBillStatus.CREATE;
        } else if (state == OrderPayState.STATE_FAIL) {
            status = AccountBillStatus.NOPASS;
        } else if (state == OrderPayState.STATE_SUCCESS) {
            status = AccountBillStatus.COMPLETE;
        } else if (state > OrderPayState.STATE_UNKNOWN) {
            status = AccountBillStatus.AUDIT;
        }

        return new Pair<Integer,Integer>(status,subStatus);
    }

    private void updateAccountBill(OrderNumWithPayNum payNumItem,Integer state) {
        Pair<Integer,Integer> status=getBillStatus(state);

        userAccountBillService.updateStatusByDealNum(payNumItem.getPayNum(), status.getKey(), status.getValue());
    }

    public void markState(PayRequest request,Integer state) {
        if (TransRequestCode.isPayCode(request.getTransRequestCode())) {
            OrderNumWithPayNum payNumItem = orderNumWithPayNumService.loadByOrderNumAndSubType(request.getOrderNo(), getBillType(request));

            if (payNumItem == null) {
                generatePayNum(request, state);
            } else {
                updateAccountBill(payNumItem, state);
            }

            AllinPayUtil.logOrderPay(logger, request, "支付订单内部状态通知:"+state);

            Integer transState=internalGetOrderState(state);

            AllinPayUtil.logOrderPay(logger, request, "支付订单外部状态通知:"+transState);

            checkValidationResult(state);

            sendOrderStateNotify(request, transState);
        }
    }

    private void checkValidationResult(Integer transState)
    {
        if(transState==OrderPayState.STATE_FAIL)
        {
            ValidationResult validationResult=new ValidationResult(ValidationResultCode.VALIDATION_ERROR_ALLINPAY_TRADE);
            PayContext.getContext().setValidationResult(validationResult);
        }
        else if(transState==OrderPayState.STATE_REMOTE_PROCESSING)
        {
            ValidationResult validationResult=new ValidationResult(ValidationResultCode.VALIDATION_ALLINPAY_PROCESSING);
            PayContext.getContext().setValidationResult(validationResult);
        }
    }

    private Integer getBillType(PayRequest request)
    {
        Integer payType=null;
        if(request.getTransRequestCode().equals(TransRequestCode.TRX_CODE_SINGLE_PAY))
        {
            payType=AccountBillSubType.TYPE_PAY;
        }
        else if(request.getTransRequestCode().equals(TransRequestCode.TRX_CODE_REPAY))
        {
            payType=AccountBillSubType.TYPE_REPAY;
        }

        return payType;
    }

    private Integer getPayType(PayRequest request)
    {
        Integer payType=null;
        if(request.getTransRequestCode().equals(TransRequestCode.TRX_CODE_SINGLE_PAY))
        {
            payType=PayType.TYPE_PAY;
        }
        else if(request.getTransRequestCode().equals(TransRequestCode.TRX_CODE_REPAY))
        {
            payType=PayType.TYPE_REPAY;
        }

        return payType;
    }

    private void sendOrderStateNotify(PayRequest request,Integer state)
    {
        PayInformPara param=new PayInformPara();
        param.setOrderId(request.getOrderNo());
        param.setState(state);
        param.setPayType(getPayType(request));

        LogUtil.info(logger, String.format("---orderNum : %s ---------------------------------------", param.getOrderId()));
        rabbitmqMessageSender.send(RabbitMqQueue.RABBIT_MQ_PAY_STATUS, param);
        LogUtil.info(logger, "----------------完成发送订单支付状态变更任务------------------");
    }

    public Integer getState(String orderNum,Integer payType) {

        Integer subType=AccountBillSubType.TYPE_PAY;
        if(payType==PayType.TYPE_PAY)
        {
            subType=AccountBillSubType.TYPE_PAY;
        }
        else if(payType==PayType.TYPE_REPAY)
        {
            subType=AccountBillSubType.TYPE_REPAY;
        }
        OrderNumWithPayNum orderNumWithPayNum = orderNumWithPayNumService.loadByOrderNumAndSubType(orderNum,subType);

        Integer state = null;

        if (orderNumWithPayNum != null) {
            state = orderNumWithPayNum.getStatus();
            if (state == null) {
                state = OrderPayState.STATE_UNKNOWN;
            }

        }
        return state;
    }

    private Integer internalGetOrderState(Integer state)
    {
        if (state == OrderPayState.STATE_BEGIN ||
                state == OrderPayState.STATE_LOCAL_PROCESSING ||
                state == OrderPayState.STATE_REMOTE_PROCESSING) {
            state = OrderPayState.STATE_PROCESSING;
        }
        return state;
    }

    /**
     * 获取订单状态调此接口
     * @param orderNum
     * @return
     */
    public Integer getOrderState(String orderNum,Integer payType) {
        Integer state = getState(orderNum, payType);

        return internalGetOrderState(state);
    }

    /**
     * 判断该订单是否已经进入支付流程
     * @param orderNum
     * @return
     */
    public boolean isInPay(String orderNum,Integer payType) {
        Integer state = getState(orderNum,payType);

        return (state>OrderPayState.STATE_UNKNOWN);
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        //userAccountBillService.updateStatusByDealNum("200290000018288-20170802111350542796",100,200);
    }
}
